/*
 * Copyright (c) 2000
 *      The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the University of
 *      California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * Written by Tom Henderson
 * Version 1.2:  August 2000  
 */

#ifndef _NETINET_STP_VAR_H_
#define _NETINET_STP_VAR_H_

/**********************************************************/
/*                                                        */
/*  stp_var.h:  Data structures, variables, and           */
/*              function prototypes 	                  */
/*                                                        */
/**********************************************************/

#include <netinet/stp.h>

/* Typedefs */
typedef int flag;

/*
 * STP common header structure.
 */
struct stphdr {
	u_short	sh_sport;		/* source port */
	u_short	sh_dport;		/* destination port */
	u_long sh_seq;			/* 24 bits of sequence number, plus */ 
					/* leading byte for type field */
	u_short sh_sum;			/* Checksum */
	u_short sh_inc;			/* Incarnation number */
};

/*
 * Stp+ip header, after ip options removed.
 */
struct stpiphdr {
	struct 	ipovly si_i;		/* overlaid ip structure */
	struct	stphdr si_s;		/* stp common header (port #s, type  */
					/* field, checksum) */
};

#define	si_next		si_i.ih_next
#define	si_prev		si_i.ih_prev
#define	si_x1		si_i.ih_x1
#define	si_pr		si_i.ih_pr
#define	si_len		si_i.ih_len
#define	si_src		si_i.ih_src
#define	si_dst		si_i.ih_dst
#define	si_sport	si_s.sh_sport
#define	si_dport	si_s.sh_dport
#define	si_seq		si_s.sh_seq
#define	si_sum		si_s.sh_sum
#define	si_inc		si_s.sh_inc

/* Structures */
struct stp_trans_pdu {
	u_long seqno;
	u_long timesent;
	int num_bytes;
	int num_trans;
};

struct stp_recv_pdu {
	u_long seqno;
	u_char received;
	int num_bytes;
};

/*
 * STP control block, one per STP.
 */
struct stpcb {
/* reassembly queue (XXX TCP requires these to be first) */
	struct  stpiphdr *seg_next; 
	struct  stpiphdr *seg_prev;

/* Protocol state-related variables */
	u_short s_state;        /* state of this connection */
	u_short s_instance; 	/* instance number for this connection */
	flag  disc_pending;   	/* Disconnect pending, but unacked data */
	flag  shutdown_pending; /* Shutdown pending, but unacked data */
	flag  oob_pending; 	/* Socket notified of oob data, but not here */
	flag  end_sent;		/* Have sent END with data */

	/* send sequence variables */
	u_long  snd_una;        /* seq no. of next in-seq. to be acknowledged */
	u_long  snd_nxt;        /* seq no. of next in-seq. to send */
	u_long  snd_wnd;        /* send window; maintained in packets */
	u_long  snd_iss;    	/* sending initial sequence number value */
	long 	snd_up;		/* send urgent pointer (send buffer offset) */
	/* receive sequence variables */
	u_long  rcv_nxt;        /* next expected in-sequence receive */
	u_long  rcv_max;        /* next expected receive */
	u_long  rcv_wnd;        /* receive window; maintained in packets */
	u_long  rcv_irs;	/* receive initial receive value */
	u_long 	rcv_up;		/* rcv urgent pointer (sequence number) */

	short ustat_pending;  	/* counter for delaying USTAT for NUM_DUP_ACKS*/
	u_long  ustat_list1;  	/* list element 1 for pending ustat */
	u_long  ustat_list2;  	/* list element 2 for pending ustat */
	u_long  last_poll_tstamp; 	/* Save last timestamp of recv. POLL */
                              	/* to ensure that STATs are not misordered */
	short cc_count;		/* count of number of outstanding cc PDUs */
/* 
 * transmit timing stuff.  See below for scale of srtt and rttvar.
 * "Variance" is actually smoothed difference.
 */
	long    s_srtt;         /* smoothed round-trip time (units = 1/8 ms) */
	long    s_rttvar;       /* variance in RTT (units = 1/8 ms) */
/*
 * Timer related variables.
 */
	u_short s_timer;
	int persist_counter;
	int keepalive_counter;
	u_long s_idle;
/*
 * Miscellaneous vars
 */
	int no_stat_response;	/* Counter zeroed each time a STAT received*/
	u_long last_send;	/* Last time we sent a datagram */
	int data_counter;	/* the buffer outstanding */
	int no_progress;	/* Increments if we get into incessant POLLing*/

/* 
 * out of band data 
 */
	char s_oobflags;	/* have some */
	char s_iobc;		/* input character */

/* STP policy-related variables (not central to formal specification) */
	u_short s_maxseg;       /* MSS (data payload) for outgoing pkts */
	u_short s_peermaxseg;   /* MSS offered by peer (for incoming pkts) */
	flag 	stp_nodelay;	/* Nagle algorithm (by default, OFF/FALSE) */
	flag	tinygram_out;	/* Records presence of outstanding tinygram */

/* congestion control (variables are maintained in bytes) */
	u_long  snd_cwnd;       /* congestion-controlled window */
	u_long  snd_ssthresh;   /* snd_cwnd size threshhold for slow start */
				/* exponential to linear switch */
	u_long  snd_recover;   	/* Don't cut down more than once per window */
	short   snd_backoff;    /* Backoff factor for retransmissions */
	short   s_softerror;    /* Possible error not yet reported */

/* Delayed send variables (used to implement a 10ms granularity for BSD) */
	int poll_pending;	/* number of ticks until next POLL can occur */
	int send_pending;	/* number of ticks until next send can occur */
	int burst_size;
	int interval;
	int trans_stack;
	int num_to_send;    	/* Number to send this interval */

/* Implementation related variables */
	struct  stpiphdr *s_template;   /* skeletal packet for transmit */
	struct  inpcb *s_inpcb; 	/* back pointer to internet pcb */
	long  snd_off;        	  /* offset from start of socket send buffer */
	u_long  bgnak_timestamp;  /* used to store timestamp to send in bgnak */
   
	struct stp_trans_pdu trans_buffer[MAXBUFFER_STP];
	struct stp_recv_pdu recv_buffer[MAXBUFFER_STP];
   
};

#ifdef KERNEL
#ifdef STP
/* global variables */
extern struct inpcbhead scb;	/* head of queue of active stpcb's */
extern struct inpcbinfo scbinfo;
u_short stp_instance; 	/* instance number for all connections */
int stp_recvspace;  	/* default size of socket recieve buffer (8192 bytes)*/
int stp_sendspace;	/* default size of socket send buffer (8192 bytes) */

/* Function prototypes */   
int  stp_attach __P((struct socket *));
void stp_slowtimo __P((void));
void stp_canceltimers __P((struct stpcb *));
struct stpcb * stp_close __P((struct stpcb *));
void stp_ctlinput __P((int, struct sockaddr *, void *));
int stp_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
void stp_disconnect __P((struct stpcb *));
void stp_shutdown __P((struct stpcb *));
struct stpcb * stp_drop __P((struct stpcb *, int));
void stp_drain __P((void));
void stp_init __P((void));
void stp_killtimers __P((struct stpcb *));
/* Input related */
void stp_input __P((struct mbuf *, int));
int validate_packet __P((u_char));
u_char stp_rcvsd __P((struct stpiphdr *, struct socket *, struct stpcb *, 
    struct mbuf *, u_long));
void stp_rcvurg __P((struct stpiphdr *, struct socket *, struct stpcb *, 
    struct mbuf *, u_long));
u_char stp_rcvpoll __P((struct stpcb *, u_long, u_long));      
void stp_rcvstat __P((struct socket *, struct stpcb *, struct mbuf *, u_long, 
    u_long, u_long));
void stp_rcvustat __P((struct socket *, struct stpcb *, u_long *, u_long));
u_char stp_rcvbgn __P((struct socket *, struct stpcb *, struct inpcb *, 
    struct mbuf *, u_long, u_long, u_long));
void stp_rcvbgnak __P((struct socket *, struct stpcb *, u_long, u_long, 
    u_long));
u_char stp_rcvend __P((struct socket *, struct stpcb *, u_long));
void stp_rcvendak __P((struct socket *, struct stpcb *, u_long));
void stp_rcvrst __P((struct socket *, struct stpcb *, struct mbuf *));
void stp_pulloutofband __P((struct socket *, struct stpiphdr *, struct mbuf *));
struct stpcb * stp_newstpcb __P((struct inpcb *));
void stp_notify __P((struct inpcb *, int));
/* Output related */
int stp_output __P((struct stpcb *, int, int));
void stp_set_output __P((struct stpcb *));
void stp_sched_output __P((struct stpcb *));
void stp_send_dummy __P((void *));
void stp_sendcc_dummy __P((void *));
int stp_sndcc_open __P((struct stpcb *, u_long));
int stp_sndcc_close __P((struct stpcb *, u_long));
int stp_sndpoll __P((struct stpcb *));
int stp_sndrst __P((struct stpcb *));
void stp_sched_poll __P((struct stpcb *));
void stp_set_poll_pending __P((struct stpcb *, int));
int stp_sndstat __P((struct stpcb *, u_long));
int stp_sndustat __P((struct stpcb *));
int stp_ustat_verify __P((struct stpcb *));
int stp_retransmit __P((struct stpcb *, u_long));
int stp_low_window __P((struct stpcb *));
u_long stp_window __P((struct stpcb *));
void stp_initialize_cwnd __P((struct stpcb *));
int stp_retransmit_list __P((struct stpcb *, u_long, u_long, int, u_long, 
    u_long));
int stp_process_list __P((struct stpcb *, u_long *, int, u_long));
struct mbuf * stp_alloc_packet __P((struct stpcb *, u_long, u_long));
void stp_finish_packet __P((struct stpcb *, struct stpiphdr *, struct mbuf *, 
    int, long));
int acked_byte_count __P((struct stpcb *, u_long));
void stp_quench __P((struct inpcb *, int));
int stp_reass __P((struct stpcb *, struct stpiphdr *, struct mbuf *));
void stp_reset __P((struct mbuf *, struct stpiphdr *));
struct stpiphdr * stp_template __P((struct stpcb *)); 
struct stpcb * stp_usrclosed __P((struct stpcb *));
int stp_usrreq __P((struct socket *, int, struct mbuf *, struct mbuf *,
    struct mbuf *));
int stp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));

void stp_opencwnd __P((struct stpcb *, int));
void stp_closecwnd __P((struct stpcb *));
void stp_updatertt __P((register struct stpcb *, int));
void stp_cancel_timer __P((struct stpcb *, int));
void stp_start_timer __P((struct stpcb *, int, int));
int time_elapsed __P((u_long));
u_long current_time __P((void));
int stp_cksum __P((struct mbuf *, int));

long seq_gt __P((u_long, u_long));
long seq_geq __P((u_long, u_long));
long seq_lt __P((u_long, u_long));
long seq_leq __P((u_long, u_long));
u_long seq_subtract __P((u_long, u_long));
u_long seq_add __P((u_long, u_long));

#endif /* STP */
#endif /* KERNEL */

#endif /* !_NETINET_STP_VAR_H_ */
